#pragma once
#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <cstring>

#include "ChainOfResponsibility.hpp"

// 默认的ket
const std::string gkey_path = "/home/xzy/112/dir13";
const int gproj_id = 0x1234;

// 标记位
#define MSGFLG_CREATE (IPC_CREAT | IPC_EXCL | 0666)
#define MSGFLG_GET (IPC_CREAT)

// 默认msgflg
const int gdefaultmsgfd = -1;

// 消息大小
#define SIZE 1024

// 服务端 1 客户端 2
const int gserverid = 1;
const int gcilentid = 2;

class MsgQueue
{
    struct msgbuf
    {
        long mtype;       /* message type, must be > 0 */
        char mtext[SIZE]; /* message data */
    };

public:
    MsgQueue()
        : _msgqid(gdefaultmsgfd)
    {
    }

    // 创建|获取消息队列
    void Create(int msgflg)
    {
        // 获取key
        key_t key = ::ftok(gkey_path.c_str(), gproj_id);

        // 创建消息队列
        _msgqid = ::msgget(key, msgflg);
        if (_msgqid < 0)
        {
            std::cerr << "msgget error" << std::endl;
            return;
        }

        std::cout << "msgget succeed : " << _msgqid << std::endl;
    }
    //ChainOfResponsibility
    // 发送消息
    void Send(int msgid)
    {
        while (true)
        {
            // 发送消息
            std::string in;
            std::cin >> in;

            // 初始化mb
            struct msgbuf mb;
            mb.mtype = msgid;
            strcpy(mb.mtext, in.c_str());

            // 发送消息
            int n = ::msgsnd(_msgqid, &mb, sizeof(mb.mtext), 0);
            if(n < 0)
            {
                std::cerr << "msgsnd error" << std::endl;
                return;
            }

            std::cout<<"msgsnd succeed"<<std::endl;
            if(in == "exit")
            {
                break;
            }
        }
    }

    // 读取消息
    void Accept(int msgid)
    {
        while(true)
        {
            struct msgbuf mb;
            int n = ::msgrcv(_msgqid,&mb,sizeof(mb.mtext),msgid,0);
            if(n < 0)
            {
                perror("msgrcv");
                //std::cerr << "msgrcv error" << std::endl;
                return;
            }
            mb.mtext[n] = 0;

            std::cout<<"msgrcv succeed" << mb.mtext <<std::endl;
            std::string text = mb.mtext;
            if(text == "exit")
            {
                std::cout<<"退出"<<std::endl;
                break;
            }

            //对消息进行加工处理
            
            HandlerEntry he;
            he.Run(text);
        }
    }

    // 销毁消息队列
    void Destroyed()
    {
        int n = ::msgctl(_msgqid, IPC_RMID, nullptr);
        if (n < 0)
        {
            std::cerr << "msgctl error" << std::endl;
            return;
        }

        std::cout << "msgctl succeed" << std::endl;
    }

    ~MsgQueue()
    {
    }

private:
    int _msgqid;
};